"""
Excel导出器

将D-Bus接口信息导出到Excel表格
"""

import os
import logging
from pathlib import Path
from typing import List, Dict, Any
from datetime import datetime
import pandas as pd
from openpyxl import Workbook
from openpyxl.styles import Font, Alignment, PatternFill, Border, Side
from openpyxl.utils.dataframe import dataframe_to_rows
from openpyxl.worksheet.table import Table, TableStyleInfo
from data_structures import DBusInterface, AnalysisResult


class ExcelExporter:
    """Excel表格导出器"""
    
    def __init__(self):
        """初始化导出器"""
        self.logger = logging.getLogger(__name__)
        
        # 定义样式
        self.header_font = Font(name='微软雅黑', size=12, bold=True, color='FFFFFF')
        self.header_fill = PatternFill(start_color='366092', end_color='366092', fill_type='solid')
        self.header_alignment = Alignment(horizontal='center', vertical='center')
        
        self.content_font = Font(name='微软雅黑', size=10)
        self.content_alignment = Alignment(horizontal='left', vertical='center', wrap_text=True)
        
        self.border = Border(
            left=Side(style='thin'),
            right=Side(style='thin'),
            top=Side(style='thin'),
            bottom=Side(style='thin')
        )
    
    def export_to_excel(self, result: AnalysisResult, output_file: str) -> bool:
        """
        导出分析结果到Excel文件
        
        Args:
            result: 分析结果
            output_file: 输出文件路径
            
        Returns:
            是否成功导出
        """
        try:
            self.logger.info(f"开始导出Excel文件: {output_file}")
            
            # 创建工作簿
            wb = Workbook()
            
            # 删除默认工作表
            wb.remove(wb.active)
            
            # 创建各个工作表
            self._create_summary_sheet(wb, result)
            self._create_interface_sheet(wb, result.interfaces)
            self._create_method_sheet(wb, result.interfaces)
            self._create_property_sheet(wb, result.interfaces)
            self._create_signal_sheet(wb, result.interfaces)
            self._create_statistics_sheet(wb, result)
            
            # 保存文件
            wb.save(output_file)
            
            self.logger.info(f"Excel文件导出成功: {output_file}")
            return True
            
        except Exception as e:
            self.logger.error(f"导出Excel文件失败: {e}")
            return False
    
    def _create_summary_sheet(self, wb: Workbook, result: AnalysisResult):
        """
        创建概览工作表
        
        Args:
            wb: 工作簿
            result: 分析结果
        """
        ws = wb.create_sheet("概览", 0)
        
        # 标题
        ws['A1'] = 'OpenBMC D-Bus接口分析报告'
        ws['A1'].font = Font(name='微软雅黑', size=16, bold=True)
        ws.merge_cells('A1:D1')
        
        # 生成时间
        ws['A3'] = '生成时间:'
        ws['B3'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        
        # 统计信息
        summary_data = [
            ['统计项目', '数量', '说明', ''],
            ['总接口数', result.total_interfaces, '所有扫描到的接口', ''],
            ['公共接口数', result.public_interfaces, '非厂商特定的标准接口', ''],
            ['总方法数', result.total_methods, '所有接口包含的方法总数', ''],
            ['总属性数', result.total_properties, '所有接口包含的属性总数', ''],
            ['总信号数', result.total_signals, '所有接口包含的信号总数', ''],
        ]
        
        # 写入数据
        for row_idx, row_data in enumerate(summary_data, start=5):
            for col_idx, value in enumerate(row_data, start=1):
                cell = ws.cell(row=row_idx, column=col_idx, value=value)
                if row_idx == 5:  # 标题行
                    cell.font = self.header_font
                    cell.fill = self.header_fill
                    cell.alignment = self.header_alignment
                else:
                    cell.font = self.content_font
                    cell.alignment = self.content_alignment
                cell.border = self.border
        
        # 分类统计
        if result.categories:
            ws['A12'] = '接口分类统计:'
            ws['A12'].font = Font(name='微软雅黑', size=12, bold=True)
            
            category_data = [['分类', '数量']]
            for category, count in result.categories.items():
                category_data.append([category, count])
            
            for row_idx, row_data in enumerate(category_data, start=13):
                for col_idx, value in enumerate(row_data, start=1):
                    cell = ws.cell(row=row_idx, column=col_idx, value=value)
                    if row_idx == 13:  # 标题行
                        cell.font = self.header_font
                        cell.fill = self.header_fill
                    else:
                        cell.font = self.content_font
                    cell.border = self.border
        
        # 错误和警告
        if result.errors or result.warnings:
            error_start_row = 13 + len(result.categories) + 3
            ws[f'A{error_start_row}'] = '错误和警告:'
            ws[f'A{error_start_row}'].font = Font(name='微软雅黑', size=12, bold=True)
            
            current_row = error_start_row + 1
            
            if result.errors:
                for error in result.errors:
                    ws[f'A{current_row}'] = f'错误: {error}'
                    ws[f'A{current_row}'].font = Font(name='微软雅黑', size=10, color='FF0000')
                    current_row += 1
            
            if result.warnings:
                for warning in result.warnings:
                    ws[f'A{current_row}'] = f'警告: {warning}'
                    ws[f'A{current_row}'].font = Font(name='微软雅黑', size=10, color='FF6600')
                    current_row += 1
        
        # 调整列宽
        ws.column_dimensions['A'].width = 20
        ws.column_dimensions['B'].width = 15
        ws.column_dimensions['C'].width = 30
        ws.column_dimensions['D'].width = 20
    
    def _create_interface_sheet(self, wb: Workbook, interfaces: List[DBusInterface]):
        """
        创建接口概览工作表
        
        Args:
            wb: 工作簿
            interfaces: 接口列表
        """
        ws = wb.create_sheet("接口概览")
        
        # 创建数据框
        data = []
        for interface in interfaces:
            data.append({
                '接口名称': interface.name,
                '命名空间': interface.namespace,
                '分类': interface.category,
                '是否公共': '是' if interface.is_public else '否',
                '方法数量': interface.method_count,
                '属性数量': interface.property_count,
                '信号数量': interface.signal_count,
                '源文件': interface.source_file,
                '接口描述': interface.description or '无描述'
            })
        
        df = pd.DataFrame(data)
        
        # 写入数据
        for r in dataframe_to_rows(df, index=False, header=True):
            ws.append(r)
        
        # 应用样式
        self._apply_table_style(ws, len(df) + 1, len(df.columns))
        
        # 调整列宽
        column_widths = [30, 20, 15, 10, 10, 10, 10, 40, 50]
        for i, width in enumerate(column_widths, start=1):
            ws.column_dimensions[chr(64 + i)].width = width
    
    def _create_method_sheet(self, wb: Workbook, interfaces: List[DBusInterface]):
        """
        创建方法详情工作表
        
        Args:
            wb: 工作簿
            interfaces: 接口列表
        """
        ws = wb.create_sheet("方法详情")
        
        data = []
        for interface in interfaces:
            for method in interface.methods:
                # 格式化输入参数
                input_params = []
                for param in method.input_params:
                    input_params.append(f"{param.name}({param.type_signature})")
                
                # 格式化输出参数
                output_params = []
                for param in method.output_params:
                    output_params.append(f"{param.name}({param.type_signature})")
                
                data.append({
                    '接口名称': interface.name,
                    '方法名称': method.name,
                    '方法描述': method.description or '无描述',
                    '输入参数': ', '.join(input_params) if input_params else '无',
                    '输入签名': method.input_signature,
                    '输出参数': ', '.join(output_params) if output_params else '无',
                    '输出签名': method.output_signature,
                    '异常': ', '.join(method.exceptions) if method.exceptions else '无',
                    '分类': interface.category,
                    '是否公共': '是' if interface.is_public else '否'
                })
        
        df = pd.DataFrame(data)
        
        # 写入数据
        for r in dataframe_to_rows(df, index=False, header=True):
            ws.append(r)
        
        # 应用样式
        self._apply_table_style(ws, len(df) + 1, len(df.columns))
        
        # 调整列宽
        column_widths = [30, 20, 40, 40, 15, 40, 15, 30, 15, 10]
        for i, width in enumerate(column_widths, start=1):
            if i <= len(column_widths):
                ws.column_dimensions[chr(64 + i)].width = width
    
    def _create_property_sheet(self, wb: Workbook, interfaces: List[DBusInterface]):
        """
        创建属性详情工作表
        
        Args:
            wb: 工作簿
            interfaces: 接口列表
        """
        ws = wb.create_sheet("属性详情")
        
        data = []
        for interface in interfaces:
            for prop in interface.properties:
                data.append({
                    '接口名称': interface.name,
                    '属性名称': prop.name,
                    '数据类型': prop.type_signature,
                    '访问权限': prop.access.value,
                    '默认值': prop.default_value or '无',
                    '单位': prop.units or '无',
                    '属性描述': prop.description or '无描述',
                    '分类': interface.category,
                    '是否公共': '是' if interface.is_public else '否'
                })
        
        df = pd.DataFrame(data)
        
        # 写入数据
        for r in dataframe_to_rows(df, index=False, header=True):
            ws.append(r)
        
        # 应用样式
        self._apply_table_style(ws, len(df) + 1, len(df.columns))
        
        # 调整列宽
        column_widths = [30, 20, 15, 15, 20, 15, 40, 15, 10]
        for i, width in enumerate(column_widths, start=1):
            ws.column_dimensions[chr(64 + i)].width = width
    
    def _create_signal_sheet(self, wb: Workbook, interfaces: List[DBusInterface]):
        """
        创建信号详情工作表
        
        Args:
            wb: 工作簿
            interfaces: 接口列表
        """
        ws = wb.create_sheet("信号详情")
        
        data = []
        for interface in interfaces:
            for signal in interface.signals:
                # 格式化信号参数
                signal_params = []
                for param in signal.params:
                    signal_params.append(f"{param.name}({param.type_signature})")
                
                data.append({
                    '接口名称': interface.name,
                    '信号名称': signal.name,
                    '信号描述': signal.description or '无描述',
                    '信号参数': ', '.join(signal_params) if signal_params else '无',
                    '参数签名': signal.signature,
                    '分类': interface.category,
                    '是否公共': '是' if interface.is_public else '否'
                })
        
        df = pd.DataFrame(data)
        
        # 写入数据
        for r in dataframe_to_rows(df, index=False, header=True):
            ws.append(r)
        
        # 应用样式
        self._apply_table_style(ws, len(df) + 1, len(df.columns))
        
        # 调整列宽
        column_widths = [30, 20, 40, 40, 20, 15, 10]
        for i, width in enumerate(column_widths, start=1):
            ws.column_dimensions[chr(64 + i)].width = width
    
    def _create_statistics_sheet(self, wb: Workbook, result: AnalysisResult):
        """
        创建统计信息工作表
        
        Args:
            wb: 工作簿
            result: 分析结果
        """
        ws = wb.create_sheet("统计分析")
        
        current_row = 1
        
        # 分类统计
        ws[f'A{current_row}'] = '接口分类统计'
        ws[f'A{current_row}'].font = Font(name='微软雅黑', size=14, bold=True)
        current_row += 2
        
        # 写入分类数据
        category_data = [['分类', '数量', '占比']]
        total = result.total_interfaces
        for category, count in result.categories.items():
            percentage = f"{count/total*100:.1f}%" if total > 0 else "0%"
            category_data.append([category, count, percentage])
        
        for row_data in category_data:
            for col_idx, value in enumerate(row_data, start=1):
                cell = ws.cell(row=current_row, column=col_idx, value=value)
                if current_row == 3:  # 标题行
                    cell.font = self.header_font
                    cell.fill = self.header_fill
                else:
                    cell.font = self.content_font
                cell.border = self.border
            current_row += 1
        
        current_row += 2
        
        # 命名空间统计
        ws[f'A{current_row}'] = '命名空间统计'
        ws[f'A{current_row}'].font = Font(name='微软雅黑', size=14, bold=True)
        current_row += 2
        
        # 写入命名空间数据
        namespace_data = [['命名空间', '数量', '占比']]
        for namespace, count in result.namespaces.items():
            percentage = f"{count/total*100:.1f}%" if total > 0 else "0%"
            namespace_data.append([namespace, count, percentage])
        
        for row_data in namespace_data:
            for col_idx, value in enumerate(row_data, start=1):
                cell = ws.cell(row=current_row, column=col_idx, value=value)
                if current_row == len(category_data) + 6:  # 标题行
                    cell.font = self.header_font
                    cell.fill = self.header_fill
                else:
                    cell.font = self.content_font
                cell.border = self.border
            current_row += 1
        
        # 调整列宽
        ws.column_dimensions['A'].width = 25
        ws.column_dimensions['B'].width = 15
        ws.column_dimensions['C'].width = 15
    
    def _apply_table_style(self, ws, max_row: int, max_col: int):
        """
        应用表格样式
        
        Args:
            ws: 工作表
            max_row: 最大行数
            max_col: 最大列数
        """
        # 应用标题样式
        for col in range(1, max_col + 1):
            cell = ws.cell(row=1, column=col)
            cell.font = self.header_font
            cell.fill = self.header_fill
            cell.alignment = self.header_alignment
            cell.border = self.border
        
        # 应用内容样式
        for row in range(2, max_row + 1):
            for col in range(1, max_col + 1):
                cell = ws.cell(row=row, column=col)
                cell.font = self.content_font
                cell.alignment = self.content_alignment
                cell.border = self.border
                
                # 交替行颜色
                if row % 2 == 0:
                    cell.fill = PatternFill(start_color='F8F9FA', end_color='F8F9FA', fill_type='solid')
